<template>
  <div class="tableIcon">
    <div class="showColumn_text">
      <span>共有{{ props.columns.length }}列，显示{{ showColumns.length }}列，隐藏{{ hideColumns.length }}列</span>
    </div>

    <!--        隐藏列-->
    <el-popover placement="bottom" width="auto" trigger="click" popper-class="showColumn_popper">
      <template #reference>
        <el-icon>
          <Setting />
        </el-icon>
      </template>
      <div class="showColumn">
        <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange"> 全选
        </el-checkbox>
        <el-checkbox-group v-model="checkedHColumn" @change="handleCheckedCitiesChange">
          <el-checkbox v-for="columnItem in props.columns"
            @change="(checked) => showColumnItem(checked, columnItem.label)" :label="columnItem.label"
            :key="columnItem.label">
            {{ columnItem.label }}
          </el-checkbox>
        </el-checkbox-group>
      </div>
    </el-popover>

    <!-- <i class="icon iconfont iconshuoming"></i> -->

    <!--        表格设置弹出框-->
    <el-popover placement="bottom" :width="370" trigger="click" popper-class="table_popper" v-if="tableList.length > 1">
      <template #reference>
        <el-icon>
          <Setting />
        </el-icon>
      </template>
      <div class="setTable">
        <span class="setHead">列表设置</span>
        <el-divider style="margin: 15px 0 25px"></el-divider>
        <div class="setContent">
          <div @click="setTableClick(item.type)" v-for="(item, index) in setTableItem" :key="index"
            :class="[tableTypeSelected === item.type ? 'active' : '']">
            <i :class="['icon', 'iconfont', item.icon]"></i>
            <span>{{ item.text }}</span>
          </div>
        </div>
      </div>
    </el-popover>
  </div>
  <div :id="props.tableId + 'commonTable'" ref="commonTable"
    :class="['commonBox', pager.isShow != false ? 'tableBox isHavePager' : 'tableBox', props.data.length == 0 ? 'notData' : '']">
    <el-table v-if="tableTypeSelected == 'table'" :data="props.data" border :stripe="true" :fit="props.isFit"
      v-bind="$attrs" tooltip-effect="light" :highlight-current-row="false" v-loading="props.isShowLoading"
      element-loading-text="Loading..." element-loading-background="rgb(131 164 255 / 16%)"
      @selection-change="handleSelectionChange" @sort-change="handleSortableChange" @expand-change="handleExpandChange"
      :cell-class-name="cellClass" :row-key="props.rowkey" :expand-row-keys="props.expandRowKeys"
      :row-class-name="rowClassName" ref="multipleTable" daotooltip-effect="dark" @row-click="toggleSelection"
      style="width: 100%" :height="props.tableHeight ? props.tableHeight : '100%'" max-height="100%"
      :show-summary="props.showSummary" :summary-method="props.summaryMethod">
      <template #empty>
        <el-image style="width: 80px" :src="noDataImg" v-if="!props.isShowLoading"></el-image>
      </template>
      <slot name="expand" />
      <slot name="table_start" />
      <slot name="table_checkbox" />
      <template v-for="item in props.columns" :key="item.label">
        <!--        单表头-->
        <!--        && !item.hidden-->
        <el-table-column v-if="!item.doubleHead && item.show" header-align="left" :key="item.prop"
          :sortable="item.sortable" :prop="item.prop" :label="item.label" :align="item.align ? item.align : 'center'"
          :fixed="item.fixed" :min-width="item.width"
          :show-overflow-tooltip="item.hasOwnProperty('overflowTooltip') ? item.overflowTooltip : true">
          <template #header>
            <div class="custom_header">
              <slot :name="item.slotName + 'Header'" :scope="item.label">
                {{ item.label }}
              </slot>
            </div>
          </template>
          <template #default="scope">
            <!-- 超出单元格内容用..显示 -->
            <template v-if="item.slotName">
              <!-- 停止插槽冒泡，会在外面包一层div，导致超长省略效果无效 -->
              <div v-if="!item.slotBubbling" @click.stop>
                <slot :name="item.slotName" :scope="scope">
                  <div v-if="item.formatter"
                    v-html="item.formatter(scope.row, scope.column, scope.row[item.prop], scope.$index)"></div>
                  <el-text v-else truncated> {{ scope.row[item.prop] }} </el-text>
                </slot>
              </div>
              <slot v-else :name="item.slotName" :scope="scope">
                <div v-if="item.formatter"
                  v-html="item.formatter(scope.row, scope.column, scope.row[item.prop], scope.$index)"></div>
                <el-text v-else truncated> {{ scope.row[item.prop] }} </el-text>
              </slot>
            </template>
            <template v-else>
              <slot :name="item.slotName" :scope="scope">
                <div v-if="item.formatter"
                  v-html="item.formatter(scope.row, scope.column, scope.row[item.prop], scope.$index)"></div>
                <el-text v-else truncated> {{ scope.row[item.prop] }} </el-text>
              </slot>
            </template>
          </template>
        </el-table-column>
        <!--        双表头-->
        <el-table-column v-else-if="item.doubleHead && item.show" :label="item.label" align="center">
          <el-table-column header-align="center" v-for="(child, childIndex) in item.child" :prop="child.prop"
            :label="child.label" :key="childIndex" :width="child.width">
            <template #header>
              <div class="custom_header">
                <slot :name="child.slotName + 'Header'" :scope="child.label">
                  {{ child.label }}
                </slot>
              </div>
            </template>
            <template #default="scope">
              <div @click.stop v-if="item.slotName">
                <slot :name="child.slotName" :scope="scope">
                  <div v-if="child.formatter"
                    v-html="child.formatter(scope.row, scope.column, scope.row[item.prop], scope.$index)"></div>
                  <template v-else>{{ scope.row[child.prop] }}</template>
                </slot>
              </div>
              <div v-else>
                <slot :name="child.slotName" :scope="scope">
                  <div v-if="child.formatter"
                    v-html="child.formatter(scope.row, scope.column, scope.row[item.prop], scope.$index)">
                  </div>
                  <template v-else>{{ scope.row[child.prop] }}</template>
                </slot>
              </div>
            </template>
          </el-table-column>
        </el-table-column>
      </template>
      <slot name="table_oper" />
    </el-table>

    <!--      表格单双列-->
    <el-row :gutter="20" class="table_double" v-else>
      <el-col :span="tableTypeSelected == 'dualCard' ? 12 : 24" class="tableRow" v-for="(item, index) in tableDeform"
        :key="index">
        <el-row class="content">
          <el-col :span="1" class="table_checkbox">
            <el-checkbox v-model="item.checkbox"></el-checkbox>
          </el-col>
          <el-col :span="22" class="grid_box" :style="{
            'grid-template-columns': tableTypeSelected == 'dualCard' ? '50% 50%' : '25% 25% 25% 25%'
          }">
            <img v-if="item.img" :src="item.img" alt="图片加载失败" />
            <p v-for="(child, index2) in item.fieldName" :key="index2" class="text">
              <span>{{ child.name }}：</span>
              <span>{{ child.value }}</span>
              <el-popover placement="top" title="详情" :width="200" trigger="click" :content="child.value">
                <template #reference>
                  <i class="el-icon-arrow-down arrow-downDetail"></i>
                </template>
              </el-popover>
            </p>
          </el-col>
        </el-row>
      </el-col>
    </el-row>
    <!--    分页-->
    <el-pagination v-if="tablePager.isShow != false" @size-change="handleSizeChange"
      @current-change="handleCurrentChange" :total="tablePager.total" :current-page="tablePager.pageNo"
      :page-size="tablePager.limit" :page-sizes="tablePager.sizes" layout="total, sizes, prev, pager, next, jumper"
      :style="{ 'margin-top': tableTypeSelected == 'table' ? '10px' : '' }"> </el-pagination>
  </div>
</template>
<script setup lang="js" name="commonTable">
import { ref, watch, nextTick, computed, onMounted } from 'vue';
import noDataImg from '../assets/notData.png';
import { useRoute } from 'vue-router';
const $route = useRoute();
// 父组件参数
const props = defineProps({
  tableId: {
    type: String,
    default: 'commonTable'
  },
  columns: {
    type: Array,
    default: () => []
  },
  data: {
    type: Array,
    default: () => []
  },
  pager: {
    type: Object,
    default: () => { }
  },
  tableHeight: {
    type: String,
    default: ''
  },
  isShowLoading: {
    type: Boolean,
    default: false
  },
  isStripe: {
    type: String,
    default: ''
  },
  tableDeform: {
    type: [Array, String],
    default: () => []
  },
  tableType: {
    type: [Array, String],
    default: () => ['table', 'dualCard', 'singleCard']
  },
  emptyText: {
    type: String,
    default: '暂无数据'
  },
  overflowTooltip: {
    type: Boolean,
    default: true
  },
  tableRowClassName: {
    type: Function,
    default: () => ''
  },
  rowkey: {
    type: String,
    default: 'id'
  },
  isFit: {
    type: Boolean,
    default: true
  },
  isHasSet: {
    type: Boolean,
    default: true
  },
  expandRowKeys: {
    type: Array,
    default: () => []
  },
  showSummary: {
    type: Boolean,
    default: false
  },
  summaryMethod: {
    type: Function,
    default: null
  },
});

const $emit = defineEmits(['setTableClick', 'handleSortableChange', 'handleSelectionChange', 'handleSizeChange', 'handleCurrentChange', 'handleRowClick']);
const multipleTable = ref({}); // 多选表格
// 变量
const currentStartIndex = ref(0); // 当前开始和结束索引
const currentEndIndex = ref(0); // 当前开始和结束索引
const checkAll = ref(false); // 全选
const checkedHColumn = ref([]); // 已选列
const hColumnOption = ref([]); // 隐藏列选项
const isIndeterminate = ref(false); // 是否为半选状态
const tableTypeSelected = ref(""); // 表格类型
const selectRow = ref([]); // 选中行
const selectData = ref([]); // 选中数据
const setTableItem = ref([]); // 设置表格明细
const tableList = ref([]); // 表格列表
const setTableItemOption = ref([
  { text: "表格", icon: "iconbiaoge1", type: "table" },
  { text: "双卡片", icon: "iconshuangpai", type: "dualCard" },
  { text: "单卡片", icon: "icondanpai", type: "singleCard" }
]);

const tooltipHide = ref(false); // 是否隐藏tooltip

const tablePager = ref(Object.assign({}, {
  isShow: true, // 是否显示分页
  total: 0, // 总条数
  pageNo: 1, // 当前页码
  limit: 10, // 每页条数
  sizes: [10, 20, 30, 50] // 每页条数选项
}, props.pager));

watch(() => props.data, () => {
  multipleTable.value.clearSelection();
});

watch(() => checkedHColumn.value, (newVal) => {
  localStorage.setItem($route.path + props.tableId, JSON.stringify(newVal));
});

watch(() => selectData.value, (data) => {
  selectRow.value = [];
  if (data.length > 0) {
    data.forEach((item) => {
      selectRow.value.push(props.data.indexOf(item));
    });
  }
});

watch(() => $route, () => {
  nextTick(() => {
    if (multipleTable.value) {
      multipleTable.value.doLayout();
    }
    let tableClass = document.querySelector(".el-table__body-wrapper");
    if (tableClass) tableClass.scrollTop = to.meta.scrollTop || 0;
  });
});

watch(() => props.pager,
  (val) => {
    let newPager = { ...tablePager.value, ...val };
    if (newPager.pageNo > 1 && newPager.pageNo > Math.ceil(val.total / val.limit)) {
      $emit("handleCurrentChange", 0);
      return;
    }
    tablePager.value = newPager;
  }, { deep: true });


const showColumns = computed(() => {
  return props.columns.filter(item => item.show);
});

const hideColumns = computed(() => {
  return props.columns.filter(item => !item.show);
});

// methods
function setUpInit() {
  tableList.value = typeof props.tableType == "string" ? props.tableType.split() : props.tableType;
  tableTypeSelected.value = tableList.value[0];
  setTableItemOption.value.forEach((item) => {
    if (tableList.value.indexOf(item.type) != -1) {
      setTableItem.value.push(item);
    }
  });
}

function handleCheckedCitiesChange(value) {
  let checkedCount = value.length;
  checkAll.value = checkedCount === props.columns.length;
  isIndeterminate.value = checkedCount > 0 && checkedCount < props.columns.length;
}

function handleSelectionChange(val) {
  selectData.value = val;
  $emit("handleSelectionChange", val);
}

function handleSizeChange(val) {
  $emit("handleSizeChange", val);
}

function handleCurrentChange(val) {
  $emit("handleCurrentChange", val - 1);
}

function handleSortableChange(sortInfo) {
  $emit("handleSortableChange", sortInfo);
}

function handleExpandChange(row, expanded) {
  let params = {
    row,
    expanded
  };
  $emit("handleExpandChange", params);
}

function formatterValue(row, column, cellValue) {
  return cellValue;
}

function toggleSelection(row) {
  multipleTable.value.toggleRowSelection(row);
  $emit("handleRowClick", row);
}

function setTableClick(type) {
  tableTypeSelected.value = type;
}

function columnsInit() {
  let storage = JSON.parse(localStorage.getItem($route.path + props.tableId)) || [];
  props.columns.forEach((item) => {
    hColumnOption.value.push(item.label);
    if (item.show) checkedHColumn.value.push(item.label);
    if (storage.length != 0) {
      item.show = storage.indexOf(item.label) !== -1 ? true : false;
    }
  });
  if (storage.length != 0) checkedHColumn.value = storage;
}

function showColumnItem(checked, label) {
  props.columns.forEach((item) => {
    if (item.label === label) item.show = checked;
  });
  nextTick(() => {
    multipleTable.value.doLayout();
  });
}

function handleCheckAllChange(val) {
  checkedHColumn.value = val ? hColumnOption.value : [];
  isIndeterminate.value = false;
  props.columns.forEach((item) => {
    item.show = val;
  });
}

function cellClass({ rowIndex }) {
  if (selectRow.value.includes(rowIndex)) {
    return "highlight";
  }
}

function rowClassName({ row, rowIndex }) {
  if (props.tableRowClassName) {
    return props.tableRowClassName({ row, rowIndex });
  }
}

onMounted(() => {
  setUpInit();
  columnsInit();
});
</script>
<style lang="less">
.field_popper {
  width: 200px;
  padding: 10px;
  padding-top: 0;

  h2 {
    text-align: center;
    font-weight: 700;
  }

  span {
    font-size: 14px;
  }
}

.tableBox {
  //height: 63vh;
  padding: 0 10px 5px;

  .table_double {
    overflow-y: auto;
  }
}

.el-pagination {
  text-align: center;
}

.el-pagination[data-v-38c21943] {
  overflow-x: auto;
}

.tableRow {
  .content {
    border: 1px solid rgba(105, 145, 254, 0.2);
    border-radius: 4px;
    margin: 10px 0;

    .grid_box {
      display: grid;
      padding: 15px 0 15px 15px;

      img {
        grid-row: 1/6;
        width: 196px;
        height: 196px;
        margin-bottom: 20px;
      }
    }

    .text {
      width: 85%;
      height: 28px;
      line-height: 28px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      position: relative;
      padding-right: 20px;

      span {
        font-size: 14px;
      }

      span:nth-of-type(1) {
        color: #567bb0;
      }

      i {
        position: absolute;
        right: 0;
        top: 50%;
        transform: translateY(-50%);
        color: #688df5;
        background: rgba(105, 145, 254, 0.2);
        cursor: pointer;
      }
    }
  }

  .table_checkbox {
    display: flex;
    align-items: center;
    justify-content: center;
    border-right: 1px solid #f5f5f5;
  }
}

.text {
  p {
    height: 40px;
  }
}

.tableIcon {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  margin-right: 15px;

  i {
    color: #a5b9cb;
    font-size: 18px;
    margin-right: 15px;
    cursor: pointer;
  }

  i:last-child {
    margin-right: 0;
  }
}

.showColumn_popper {
  .showColumn {
    max-height: 400px;
    overflow-y: auto;

    .el-checkbox {
      display: block;
      padding: 10px 0;
    }
  }
}

.showColumn_text {
  display: inline-block;
  font-size: 12px;
  margin-right: 12px;
  color: #909399;
}

.notData {
  :deep(.el-table__empty-block) {
    width: 100% !important;
  }
}

.arrow-downDetail {
  font-size: 12px;
  border-radius: 2px;
  width: 15px;
  height: 15px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.highlight {
  background-color: rgba(0, 137, 158, 0.2) !important;
}

.tableImg {
  width: 60px;
  height: 60px;
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 0 auto;
}

/*.el-tab-pane {
  //解决tab页表格高度不生效
  height: calc(100vh - 180px);
}*/
</style>
